import { getFormByProcessId, startProcess, detail, completeTask, transferTask, delegateTask, rollbackTask, terminateProcess, addMultiInstance, withdrawTask } from '@/api/plugin/workflow/process'

import Layout from '@/page/index/'
import defaultValues from './default-values'

import Print from '../util/print'
import Watermark from '../util/watermark'

import { mapGetters } from 'vuex'

export default {
  mixins: [defaultValues],
  computed: {
    ...mapGetters(['tag', 'userInfo', 'permission']),
  },
  data() {
    return {
      process: {}, // 流程定义/流程实例信息
      buttonList: [], // 配置按钮信息
      flow: [], // 流转信息
      userSelectType: '', // 人员选择类型 transfer转办 delegate委托 copy抄送 assignee审核人
      checkType: 'radio', // 人员选择check类型 radio单选 checkbox多选
      comment: '', // 评论
      bpmnOption: {}, // 流程图配置信息
      defaultChecked: '', // 人员选择默认选中
      waiting: true, // 骨架屏加载中
    }
  },
  methods: {
    // 动态路由跳转
    dynamicRoute(row, type, async = false) {
      const { id, taskId, processInstanceId, processId, formKey, formUrl } = row
      let param = Buffer.from(JSON.stringify({
        processId: id,
        taskId,
        processInsId: processInstanceId || processId
      })).toString('base64')

      if (formKey && formKey.startsWith('wf_ex_')) {
        if (formUrl) { // 配置了自定义路由
          this.$router.push(formUrl + `?p=${param}`)
        } else { // 动态添加路由
          this.$router.addRoutes([{
            path: `/workflow/process/external`,
            component: Layout,
            children: [{
              path: `${formKey.substring(6)}/${type}`,
              name: type == 'start' ? '发起流程' : '流程详情',
              component: () =>
                import( /* webpackChunkName: "views" */ `@/views/plugin/workflow/process/external/${formKey.substring(6)}/${type}.vue`),
            }]
          }])
          this.$router.push(`/workflow/process/external/${formKey.substring(6)}/${type}?p=${param}`)
          this.handleCloseTag()
        }
      } else {
        if (async) {
          return new Promise((resolve) => {
            resolve({ row, type, param })
          })
        } else {
          this.$router.push(`/workflow/process/${type}/${param}`)
        }
      }
    },
    // 根据可读可写，过滤avue column
    filterAvueColumn(column, taskForm, isExForm = false, props = { label: 'label', prop: 'prop' }) {
      const _this = this

      if (!column || column.length == 0) return { column, vars: [] }

      const values = []
      const vars = []
      column.forEach(col => {
        let c = taskForm.find(s => s.id == col[props.prop])
        if (c && c.readable) {
          // /**
          //  * @deprecated 与节点配置可读可写冲突
          //  */
          // if (!c) { // 未重新点击节点设计表单字段可读可写。
          //   if ((this.process.isOwner && this.process.status == 'todo') || !this.process.hasOwnProperty('isOwner')) c = { readable: true, writable: true }
          //   else c = { readable: true, writable: false }
          // }
          if (!isExForm) { // 非外置表单 处理事件
            let event = ['change', 'blur', 'click', 'focus']
            event.forEach(e => {
              if (col[e]) col[e] = eval((col[e] + '').replace(/this/g, '_this'))
            })
            if (col.event) Object.keys(col.event).forEach(key => col.event[key] = eval((col.event[key] + '').replace(/this/g, '_this')))
          }
          if (c.writable) { // 可写，记录需要提交的字段、处理字段默认值
            vars.push(col[props.prop])
            if (col.value) col.value = _this.getDefaultValues(col.value)
          } else { // 不可写，清除校验、默认值
            if (col.type == 'dynamic') {
              col.children.addBtn = false
              col.children.delBtn = false
            } else {
              col.readonly = true
              col.disabled = true
            }
            delete col.rules
            delete col.value
            // delete col.event
            // event.forEach(e => delete col[e])
          }
          if (col.type == 'dynamic') { // 处理子表单
            col.children.column = _this.filterAvueColumn(col.children.column, taskForm).column
          }
          if (col.rules && col.pattern) { // 处理正则
            col.rules.forEach(c => {
              if (c.pattern) c.pattern = new RegExp(col.pattern)
            })
          }

          values.push(col)
        }
      })
      return { column: values, vars }
    },
    /**
     * 获取流程发起表单
     * @param processId 流程定义id
     * @returns Promise({"process": "流程定义信息", "startForm": "开始节点表单"})
     */
    getStartForm(processId) {
      return new Promise((resolve, reject) => {
        getFormByProcessId({ processId }).then(res => {
          const { process } = res.data.data
          process.hideComment = true
          this.process = process
          this.tag.label = '发起流程 - ' + process.name
          resolve(res.data.data)
        }).catch(() => {
          reject()
        })
      })
    },
    /**
     * 发起流程
     * @param form {"processId": "流程定义id", ...表单自定义字段变量}
     */
    handleStartProcess() {
      this.loading = true
      this.$refs.form.validate((valid, done, msg) => {
        let form = this.deepClone(this.form)
        if (this.$refs.examineForm && this.$refs.examineForm.examineForm) {
          const { copyUser, assignee } = this.$refs.examineForm.examineForm
          form = { ...form, copyUser, assignee }
        }
        if (valid) {
          startProcess(form).then(() => {
            this.$message.success("发起成功")
            this.handleCloseTag('/plugin/workflow/process/send')
            done()
            this.loading = false
          }).catch(() => {
            done()
            this.loading = false
          })
        } else {
          done()
          this.loading = false
          if (msg) {
            const key = Object.keys(msg)[0]
            const rules = msg[key]
            this.$message.error(rules.map(r => r.message).join(' | '))
          }
        }
      })
    },
    /**
     * 获取流程任务详情
     * @param taskId 任务id
     * @param processInsId 流程实例id
     * @returns Promise({"process": "流程实例信息", "form": "表单信息", "flow": "流转信息", "button": "配置按钮信息", "bpmnOption": "流程图配置"})
     */
    getTaskDetail(taskId, processInsId) {
      return new Promise((resolve, reject) => {
        detail({ taskId, processInsId }).then(res => {
          const { process, form, flow, button, nodeResult} = res.data.data
          const { xml } = process

          const bpmnOption = {
            mode: 'view', xml,
            flows: this.handleResolveFlows(flow)
          }
          this.process = process
          this.flow = flow
          this.buttonList = button
          this.bpmnOption = bpmnOption
          this.tag.label = '流程详情 - ' + process.processDefinitionName
          resolve({ process, form, flow, button, bpmnOption, nodeResult})
        }).catch(() => {
          reject()
        })
      })
    },
    /**
     * 任务审核
     * @param pass 驳回/通过
     */
    handleCompleteTask(pass, variables) {
      return new Promise((resolve, reject) => {
        const { comment, copyUser, assignee, attachment } = this.$refs.examineForm.examineForm
        if (!pass && !comment) {
          this.$message.error("请填写批复意见")
          this.submitLoading = false
          reject()
          return
        }
        const { taskId, processInstanceId, processDefinitionName, processDefinitionId } = this.process
        const param = {
          taskId, processInstanceId, processDefinitionName, processDefinitionId, pass,
          comment, copyUser, assignee, variables, attachment
        }
        completeTask(param).then(() => {
          resolve()
        }).catch(() => {
          reject()
        })
      })
    },
    /**
     * 驳回到指定节点
     * @param nodeId 节点id
     */
    handleRollbackTask(nodeId) {
      const { taskId } = this.process
      rollbackTask({ comment: this.comment, nodeId, taskId }).then(() => {
        this.$message.success("回退成功")
        this.handleCloseTag('/plugin/workflow/process/todo')
      })
    },
    /**
     * 终止流程
     */
    handleTerminateProcess() {
      const comment = this.comment
      if (!comment) {
        this.$message.error("请填写批复意见")
        return
      }
      this.$confirm('确定要终止此流程吗?', '警告', {
        type: 'warning'
      }).then(() => {
        const { taskId } = this.process

        terminateProcess({ taskId, comment }).then(() => {
          this.$message.success("操作成功")
          this.handleCloseTag('/plugin/workflow/process/todo')
        })
      }).catch(() => {

      })
    },
    // 人员选择弹窗
    handleUserSelect({ type, checkType }) {
      if (!this.comment && ['transfer', 'delegate'].includes(type)) {
        this.$message.error("请填写批复意见")
        return
      }
      if (type == 'assignee') this.defaultChecked = this.$refs.examineForm.examineForm.assignee
      else if (type == 'copy') this.defaultChecked = this.$refs.examineForm.examineForm.copyUser

      this.$refs['user-select'].visible = true
      this.userSelectType = type
      this.checkType = checkType
    },
    // 选人回调
    handleUserSelectConfirm(id, name) {
      const { comment, copyUser } = this.$refs.examineForm.examineForm
      const { taskId, processInstanceId, processDefinitionName, processDefinitionId } = this.process

      const type = this.userSelectType
      const param = {
        taskId, processInstanceId, processDefinitionName, processDefinitionId,
        assignee: id,
        comment, copyUser
      }
      if (type == 'transfer') {
        transferTask(param).then(() => { // 转办
          this.$message.success("转办成功")
          this.handleCloseTag('/plugin/workflow/process/todo')
        })
      } else if (type == 'delegate') { // 委托
        delegateTask(param).then(() => {
          this.$message.success("委托成功")
          this.handleCloseTag('/plugin/workflow/process/todo')
        })
      } else if (type == 'addInstance') { // 加签
        addMultiInstance(param).then(() => {
          this.$message.success("加签成功")
        })
      } else if (type == 'copy') { // 抄送
        this.$refs.examineForm.examineForm.copyUser = id
        this.$refs.examineForm.examineForm.$copyUser = name
      } else if (type == 'assignee') { // 指定下一步审批人
        this.$refs.examineForm.examineForm.assignee = id
        this.$refs.examineForm.examineForm.$assignee = name
      }
      this.$refs['user-select'].visible = false
    },
    handleWithdrawTask() {
      const { taskId } = this.process
      this.$confirm('<p><span style="color: red;">撤销：</span>撤销终止此流程</p><p><span style="color: red;">撤回：</span>撤回到发起人重新提交，若当前流程不存在发起人节点，功能同撤销</p>', '请选择撤销/撤回操作', {
        type: 'warning',
        distinguishCancelAndClose: true,
        confirmButtonText: '撤销',
        cancelButtonText: '撤回',
        dangerouslyUseHTMLString: true
      }).then(() => {
        withdrawTask({ taskId, withdrawType: 'wf_withdraw_end' }).then(() => {
          this.$message.success("操作成功")
          this.handleCloseTag('/plugin/workflow/process/todo')
        })
      }).catch((action) => {
        if (action == 'cancel') {
          withdrawTask({ taskId, withdrawType: 'wf_withdraw_start' }).then(() => {
            this.$message.success("操作成功")
            this.handleCloseTag('/plugin/workflow/process/todo')
          })
        }
      })
    },
    handlePrint() { // 打印
      const loading = this.$loading({
        lock: true,
        text: 'Loading',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      const option = this.deepClone(this.option)
      this.option.detail = true
      if (this.option.column) {
        this.option.column.forEach(col => {
          this.handleTemporaryPrintOption(col)
        })
      }
      if (this.option.group) {
        this.option.group.forEach(g => {
          g.column.forEach(col => {
            this.handleTemporaryPrintOption(col)
          })
        })
      }
      // 汇总表单打印
      const summaryOption = this.deepClone(this.summaryOption)
      if (this.summaryOption.group) {
        this.summaryOption.group.forEach(g => {
          g.collapse = false
          g.column.forEach(col => {
            this.handleTemporaryPrintOption(col)
          })
          setTimeout(() => {
            g.collapse = true
          })
        })
      }
      setTimeout(() => {
        loading.close()
        // const watermarkText = this.userInfo.user_name + " " + this.userInfo.dept_name
        // Watermark.set({ watermark_txt: watermarkText }) // 添加水印
        Print('#printBody')
        this.option = option
        this.summaryOption = summaryOption
        Watermark.remove() // 删除水印
      }, 500)
    },
    // 生成打印临时option
    handleTemporaryPrintOption(obj) {
      if (!obj.type) return
      obj.span = 24
      if (obj.type == 'dynamic') {
        obj.children.type = 'form'
        obj.children.column.forEach(col => {
          this.handleTemporaryPrintOption(col)
        })
      }
    },
    // 关闭当前tag，并跳转
    handleCloseTag(path) {
      this.$store.commit('DEL_TAG', this.tag)
      if (path) this.$router.push(path)
    },
    handleResolveFlows(flow) {
      const flows = []

      flow.forEach(f => {
        let { assigneeName, createTime, endTime, comments } = f

        if ((/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent))) { // safari
          createTime = createTime.replace(/-/g, '/')
          endTime = endTime.replace(/-/g, '/')
        }

        const ff = {
          id: f.historyActivityId,
          class: (!endTime && f.historyActivityType != 'candidate') ? 'nodePrimary' : ''
        }
        let tooltip = ''
        if (assigneeName) {
          tooltip = `<span title='${assigneeName}'>${assigneeName}</span><br>`
          if (createTime) tooltip += `<span title='${createTime}'>${this.dateFormat(new Date(createTime), 'yyyy-MM-dd hh:mm')}</span><br>`

          if (comments && comments.length > 0) {
            let comment
            let { type, fullMessage } = comments.find(c => c.action == 'AddComment') || {}

            if (type == 'assigneeComment') {
              comment = '变更审核人：' + fullMessage
              ff.class = 'nodeWarn'
            }
            if (type == 'dispatchComment') {
              comment = '调度：' + fullMessage
              ff.class = 'nodeWarn'
            }
            if (type == 'transferComment') {
              comment = '转办：' + fullMessage
              ff.class = 'nodeWarn'
            }
            if (type == 'delegateComment') {
              comment = '委托：' + fullMessage
              ff.class = 'nodeWarn'
            }
            if (type == 'rollbackComment') {
              comment = '驳回：' + fullMessage
              ff.class = 'nodeError'
            }
            if (type == 'terminateComment') {
              comment = '终止：' + fullMessage
              ff.class = 'nodeError'
            }
            if (type == 'addMultiInstanceComment') {
              comment = '加签：' + fullMessage
              ff.class = 'nodeWarn'
            }
            if (type == 'deleteMultiInstanceComment') {
              comment = '减签：' + fullMessage
              ff.class = 'nodeError'
            }
            if (type == 'withdrawComment') {
              comment = '撤销：' + fullMessage
              ff.class = 'nodeWarn'
            }
            if (type == 'comment') {
              comment = '审批：' + fullMessage
              ff.class = 'nodeSuccess'
            }
            if (comment) tooltip += `<span title='${comment}'>${comment}</span>`
          }
          ff.tooltip = tooltip
        }

        if (f.historyActivityType == 'sequenceFlow') ff.class = 'lineWarn'
        else if (!ff.class && f.historyActivityType != 'candidate') ff.class = 'nodeSuccess'

        const index = flows.findIndex(fl => fl.id == f.historyActivityId)
        if (index != -1) flows.splice(index, 1, ff)
        else flows.push(ff)
      })
      return flows
    },
    // 上传组件预览
    handleUploadPreview(file, column, done) {
      const { url } = file
      const { video, img } = this.$typeList
      if (video.test(url) || img.test(url)) done()
      else window.open(url)
    },
  }
}
